import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class SimpleServer {
    
    // 数据库配置
    private static final String DB_URL = "jdbc:mysql://localhost:3306/hospital_queue?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "ysf191025";
    
    // 内存中的排队管理
    private static final Map<Integer, AtomicInteger> departmentCounters = new ConcurrentHashMap<>();
    private static final Map<Integer, String> departmentPrefixes = new HashMap<>();
    
    static {
        // 初始化科室前缀
        departmentPrefixes.put(1, "A"); // 内科
        departmentPrefixes.put(2, "B"); // 外科
        departmentPrefixes.put(3, "C"); // 儿科
        departmentPrefixes.put(4, "D"); // 妇产科
        
        // 初始化计数器
        for (int i = 1; i <= 4; i++) {
            departmentCounters.put(i, new AtomicInteger(0));
        }
        
        // 加载MySQL驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8081), 0);
        
        // 静态文件处理器
        server.createContext("/", new StaticFileHandler());
        
        // API处理器
        server.createContext("/api/departments", new DepartmentHandler());
        server.createContext("/api/doctors", new DoctorHandler());
        server.createContext("/api/queue", new QueueHandler());
        
        server.setExecutor(null);
        server.start();
        
        System.out.println("服务器启动在 http://localhost:8081");
        System.out.println("医院排队叫号系统已启动 (数据库版本)");
        System.out.println("访问: http://localhost:8081/index.html");
        System.out.println("按 Ctrl+C 停止服务器");
    }
    
    // 获取数据库连接
    private static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    }
    
    // 静态文件处理器
    static class StaticFileHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String path = exchange.getRequestURI().getPath();
            if (path.equals("/")) {
                path = "/index.html";
            }
            
            Path filePath = Paths.get("deploy/yiyuan" + path);
            
            if (Files.exists(filePath) && !Files.isDirectory(filePath)) {
                String contentType = getContentType(path);
                exchange.getResponseHeaders().set("Content-Type", contentType);
                exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
                
                byte[] fileBytes = Files.readAllBytes(filePath);
                exchange.sendResponseHeaders(200, fileBytes.length);
                OutputStream os = exchange.getResponseBody();
                os.write(fileBytes);
                os.close();
            } else {
                exchange.sendResponseHeaders(404, 0);
                exchange.getResponseBody().close();
            }
        }
        
        private String getContentType(String path) {
            if (path.endsWith(".html")) return "text/html; charset=utf-8";
            if (path.endsWith(".css")) return "text/css; charset=utf-8";
            if (path.endsWith(".js")) return "application/javascript; charset=utf-8";
            if (path.endsWith(".json")) return "application/json; charset=utf-8";
            return "text/plain; charset=utf-8";
        }
    }
    
    // 科室API处理器
    static class DepartmentHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
            exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
            
            try (Connection conn = getConnection()) {
                String sql = "SELECT id, name, description FROM department WHERE status = 1";
                PreparedStatement stmt = conn.prepareStatement(sql);
                ResultSet rs = stmt.executeQuery();
                
                List<Map<String, Object>> departments = new ArrayList<>();
                while (rs.next()) {
                    Map<String, Object> dept = new HashMap<>();
                    dept.put("id", rs.getInt("id"));
                    dept.put("name", rs.getString("name"));
                    dept.put("description", rs.getString("description"));
                    departments.add(dept);
                }
                
                String response = buildDepartmentsJson(departments);
                exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes("UTF-8"));
                os.close();
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"error\":\"数据库连接失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
    }
    
    // 医生API处理器
    static class DoctorHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
            exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
            
            String query = exchange.getRequestURI().getQuery();
            int departmentId = 0;
            
            if (query != null && query.contains("departmentId=")) {
                String[] params = query.split("&");
                for (String param : params) {
                    if (param.startsWith("departmentId=")) {
                        departmentId = Integer.parseInt(param.split("=")[1]);
                        break;
                    }
                }
            }
            
            try (Connection conn = getConnection()) {
                String sql = "SELECT id, name, title, department_id FROM doctor WHERE status = 1";
                if (departmentId > 0) {
                    sql += " AND department_id = ?";
                }
                
                PreparedStatement stmt = conn.prepareStatement(sql);
                if (departmentId > 0) {
                    stmt.setInt(1, departmentId);
                }
                
                ResultSet rs = stmt.executeQuery();
                
                List<Map<String, Object>> doctors = new ArrayList<>();
                while (rs.next()) {
                    Map<String, Object> doctor = new HashMap<>();
                    doctor.put("id", rs.getInt("id"));
                    doctor.put("name", rs.getString("name"));
                    doctor.put("title", rs.getString("title"));
                    doctor.put("departmentId", rs.getInt("department_id"));
                    doctors.add(doctor);
                }
                
                String response = buildDoctorsJson(doctors);
                exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes("UTF-8"));
                os.close();
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"error\":\"数据库连接失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
    }
    
    // 排队API处理器
    static class QueueHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
            exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
            
            String method = exchange.getRequestMethod();
            String path = exchange.getRequestURI().getPath();
            
            if ("POST".equals(method) && "/api/queue".equals(path)) {
                handleQueueRequest(exchange);
            } else if ("GET".equals(method) && "/api/queue/current".equals(path)) {
                handleCurrentQueue(exchange);
            } else if ("GET".equals(method) && "/api/queue/stats".equals(path)) {
            handleQueueStats(exchange);
        } else if ("GET".equals(method) && "/api/queue/waiting".equals(path)) {
            handleWaitingQueue(exchange);
        } else if ("POST".equals(method) && "/api/queue/call-next".equals(path)) {
            handleCallNext(exchange);
        } else if ("POST".equals(method) && "/api/queue/call-specific".equals(path)) {
            handleCallSpecific(exchange);
        } else if ("POST".equals(method) && "/api/queue/complete".equals(path)) {
            handleCompletePatient(exchange);
        } else {
            exchange.sendResponseHeaders(404, 0);
            exchange.getResponseBody().close();
        }
        }
        
        private void handleQueueRequest(HttpExchange exchange) throws IOException {
            try {
                // 读取POST数据
                InputStream is = exchange.getRequestBody();
                String postData = new String(is.readAllBytes(), "UTF-8");
                Map<String, String> params = parseFormData(postData);
                
                String patientName = params.get("patientName");
                String patientPhone = params.get("patientPhone");
                String departmentIdStr = params.get("departmentId");
                String doctorIdStr = params.get("doctorId");
                
                // 验证必需参数
                if (patientName == null || patientName.trim().isEmpty() ||
                    patientPhone == null || patientPhone.trim().isEmpty() ||
                    departmentIdStr == null || departmentIdStr.trim().isEmpty() ||
                    doctorIdStr == null || doctorIdStr.trim().isEmpty()) {
                    
                    String error = "{\"success\":false,\"message\":\"请填写完整的患者信息\"}";
                    exchange.sendResponseHeaders(400, error.getBytes("UTF-8").length);
                    OutputStream os = exchange.getResponseBody();
                    os.write(error.getBytes("UTF-8"));
                    os.close();
                    return;
                }
                
                int departmentId, doctorId;
                try {
                    departmentId = Integer.parseInt(departmentIdStr.trim());
                    doctorId = Integer.parseInt(doctorIdStr.trim());
                } catch (NumberFormatException e) {
                    String error = "{\"success\":false,\"message\":\"科室或医生选择无效\"}";
                    exchange.sendResponseHeaders(400, error.getBytes("UTF-8").length);
                    OutputStream os = exchange.getResponseBody();
                    os.write(error.getBytes("UTF-8"));
                    os.close();
                    return;
                }
                
                // 生成排队号码
                String queueNumber = generateQueueNumber(departmentId);
                
                // 保存到数据库
                try (Connection conn = getConnection()) {
                    String sql = "INSERT INTO queue_record (patient_name, patient_phone, department_id, doctor_id, queue_number, status) VALUES (?, ?, ?, ?, ?, 0)";
                    PreparedStatement stmt = conn.prepareStatement(sql);
                    stmt.setString(1, patientName);
                    stmt.setString(2, patientPhone);
                    stmt.setInt(3, departmentId);
                    stmt.setInt(4, doctorId);
                    stmt.setString(5, queueNumber);
                    
                    int result = stmt.executeUpdate();
                    
                    if (result > 0) {
                        String jsonResponse = "{\"success\":true,\"queueNumber\":\"" + queueNumber + "\",\"message\":\"排队成功\"}";
                        exchange.sendResponseHeaders(200, jsonResponse.getBytes("UTF-8").length);
                        OutputStream os = exchange.getResponseBody();
                        os.write(jsonResponse.getBytes("UTF-8"));
                        os.close();
                    } else {
                        throw new SQLException("插入失败");
                    }
                }
                
            } catch (Exception e) {
                e.printStackTrace();
                String error = "{\"success\":false,\"message\":\"排队失败：" + e.getMessage() + "\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private void handleCurrentQueue(HttpExchange exchange) throws IOException {
            try (Connection conn = getConnection()) {
                // 获取当前正在就诊的患者
                String currentSql = "SELECT queue_number, patient_name FROM queue_record WHERE status = 1 ORDER BY called_at DESC LIMIT 1";
                PreparedStatement currentStmt = conn.prepareStatement(currentSql);
                ResultSet currentRs = currentStmt.executeQuery();
                
                String currentQueueNumber = "无";
                String currentPatientName = "无";
                
                if (currentRs.next()) {
                    currentQueueNumber = currentRs.getString("queue_number");
                    currentPatientName = currentRs.getString("patient_name");
                }
                
                // 获取等待人数
                String waitingSql = "SELECT COUNT(*) as count FROM queue_record WHERE status = 0";
                PreparedStatement waitingStmt = conn.prepareStatement(waitingSql);
                ResultSet waitingRs = waitingStmt.executeQuery();
                
                int waiting = 0;
                if (waitingRs.next()) {
                    waiting = waitingRs.getInt("count");
                }
                
                // 估算等待时间（每人平均15分钟）
                int estimatedWait = waiting * 15;
                
                String jsonResponse = "{\"current\":{\"queueNumber\":\"" + currentQueueNumber + 
                                    "\",\"patientName\":\"" + currentPatientName + 
                                    "\"},\"waiting\":" + waiting + 
                                    ",\"estimatedWait\":" + estimatedWait + "}";
                
                exchange.sendResponseHeaders(200, jsonResponse.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(jsonResponse.getBytes("UTF-8"));
                os.close();
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"error\":\"数据库连接失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private void handleQueueStats(HttpExchange exchange) throws IOException {
            try (Connection conn = getConnection()) {
                // 今日统计
                String todaySql = "SELECT COUNT(*) as total, " +
                                "SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as completed, " +
                                "SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as waiting " +
                                "FROM queue_record WHERE DATE(created_at) = CURDATE()";
                
                PreparedStatement stmt = conn.prepareStatement(todaySql);
                ResultSet rs = stmt.executeQuery();
                
                int total = 0, completed = 0, waiting = 0;
                if (rs.next()) {
                    total = rs.getInt("total");
                    completed = rs.getInt("completed");
                    waiting = rs.getInt("waiting");
                }
                
                String jsonResponse = "{\"today\":{\"total\":" + total + 
                                    ",\"completed\":" + completed + 
                                    ",\"waiting\":" + waiting + "}}";
                
                exchange.sendResponseHeaders(200, jsonResponse.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(jsonResponse.getBytes("UTF-8"));
                os.close();
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"error\":\"数据库连接失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private String generateQueueNumber(int departmentId) {
            String prefix = departmentPrefixes.getOrDefault(departmentId, "X");
            int number = departmentCounters.get(departmentId).incrementAndGet();
            return prefix + String.format("%03d", number);
        }
        
        private void handleWaitingQueue(HttpExchange exchange) throws IOException {
            try (Connection conn = getConnection()) {
                String sql = "SELECT queue_number, patient_name, patient_phone FROM queue_record WHERE status = 0 ORDER BY created_at ASC";
                PreparedStatement stmt = conn.prepareStatement(sql);
                ResultSet rs = stmt.executeQuery();
                
                StringBuilder json = new StringBuilder("[");
                boolean first = true;
                while (rs.next()) {
                    if (!first) json.append(",");
                    json.append("{")
                        .append("\"queueNumber\":\"").append(rs.getString("queue_number")).append("\",")
                        .append("\"patientName\":\"").append(rs.getString("patient_name")).append("\",")
                        .append("\"patientPhone\":\"").append(rs.getString("patient_phone")).append("\"")
                        .append("}");
                    first = false;
                }
                json.append("]");
                
                String response = json.toString();
                exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes("UTF-8"));
                os.close();
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"error\":\"数据库连接失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private void handleCallNext(HttpExchange exchange) throws IOException {
            try (Connection conn = getConnection()) {
                // 先完成当前患者（如果有的话）
                String completeSql = "UPDATE queue_record SET status = 2, completed_at = NOW() WHERE status = 1";
                PreparedStatement completeStmt = conn.prepareStatement(completeSql);
                completeStmt.executeUpdate();
                
                // 叫下一位患者
                String nextSql = "SELECT queue_number, patient_name FROM queue_record WHERE status = 0 ORDER BY created_at ASC LIMIT 1";
                PreparedStatement nextStmt = conn.prepareStatement(nextSql);
                ResultSet rs = nextStmt.executeQuery();
                
                if (rs.next()) {
                    String queueNumber = rs.getString("queue_number");
                    String patientName = rs.getString("patient_name");
                    
                    // 更新状态为正在就诊
                    String updateSql = "UPDATE queue_record SET status = 1, called_at = NOW() WHERE queue_number = ?";
                    PreparedStatement updateStmt = conn.prepareStatement(updateSql);
                    updateStmt.setString(1, queueNumber);
                    updateStmt.executeUpdate();
                    
                    String response = "{\"success\":true,\"queueNumber\":\"" + queueNumber + "\",\"patientName\":\"" + patientName + "\"}";
                    exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                    OutputStream os = exchange.getResponseBody();
                    os.write(response.getBytes("UTF-8"));
                    os.close();
                } else {
                    String response = "{\"success\":false,\"message\":\"没有等待的患者\"}";
                    exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                    OutputStream os = exchange.getResponseBody();
                    os.write(response.getBytes("UTF-8"));
                    os.close();
                }
                
            } catch (SQLException e) {
                e.printStackTrace();
                String error = "{\"success\":false,\"message\":\"操作失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private void handleCallSpecific(HttpExchange exchange) throws IOException {
            try {
                InputStream is = exchange.getRequestBody();
                String postData = new String(is.readAllBytes(), "UTF-8");
                Map<String, String> params = parseFormData(postData);
                String queueNumber = params.get("queueNumber");
                
                try (Connection conn = getConnection()) {
                    // 先完成当前患者（如果有的话）
                    String completeSql = "UPDATE queue_record SET status = 2, completed_at = NOW() WHERE status = 1";
                    PreparedStatement completeStmt = conn.prepareStatement(completeSql);
                    completeStmt.executeUpdate();
                    
                    // 叫指定患者
                    String updateSql = "UPDATE queue_record SET status = 1, called_at = NOW() WHERE queue_number = ? AND status = 0";
                    PreparedStatement updateStmt = conn.prepareStatement(updateSql);
                    updateStmt.setString(1, queueNumber);
                    int result = updateStmt.executeUpdate();
                    
                    if (result > 0) {
                        String response = "{\"success\":true,\"queueNumber\":\"" + queueNumber + "\"}";
                        exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                        OutputStream os = exchange.getResponseBody();
                        os.write(response.getBytes("UTF-8"));
                        os.close();
                    } else {
                        String response = "{\"success\":false,\"message\":\"患者不存在或已被叫号\"}";
                        exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                        OutputStream os = exchange.getResponseBody();
                        os.write(response.getBytes("UTF-8"));
                        os.close();
                    }
                }
                
            } catch (Exception e) {
                e.printStackTrace();
                String error = "{\"success\":false,\"message\":\"操作失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }
        
        private void handleCompletePatient(HttpExchange exchange) throws IOException {
            try {
                InputStream is = exchange.getRequestBody();
                String postData = new String(is.readAllBytes(), "UTF-8");
                Map<String, String> params = parseFormData(postData);
                String queueNumber = params.get("queueNumber");
                
                try (Connection conn = getConnection()) {
                    String updateSql = "UPDATE queue_record SET status = 2, completed_at = NOW() WHERE queue_number = ? AND status = 1";
                    PreparedStatement updateStmt = conn.prepareStatement(updateSql);
                    updateStmt.setString(1, queueNumber);
                    int result = updateStmt.executeUpdate();
                    
                    if (result > 0) {
                        String response = "{\"success\":true,\"message\":\"患者就诊完成\"}";
                        exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                        OutputStream os = exchange.getResponseBody();
                        os.write(response.getBytes("UTF-8"));
                        os.close();
                    } else {
                        String response = "{\"success\":false,\"message\":\"患者不存在或状态异常\"}";
                        exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
                        OutputStream os = exchange.getResponseBody();
                        os.write(response.getBytes("UTF-8"));
                        os.close();
                    }
                }
                
            } catch (Exception e) {
                e.printStackTrace();
                String error = "{\"success\":false,\"message\":\"操作失败\"}";
                exchange.sendResponseHeaders(500, error.getBytes("UTF-8").length);
                OutputStream os = exchange.getResponseBody();
                os.write(error.getBytes("UTF-8"));
                os.close();
            }
        }

        private Map<String, String> parseFormData(String formData) throws UnsupportedEncodingException {
            Map<String, String> params = new HashMap<>();
            String[] pairs = formData.split("&");
            for (String pair : pairs) {
                String[] keyValue = pair.split("=");
                if (keyValue.length == 2) {
                    String key = URLDecoder.decode(keyValue[0], "UTF-8");
                    String value = URLDecoder.decode(keyValue[1], "UTF-8");
                    params.put(key, value);
                }
            }
            return params;
        }
    }
    
    // 手动构建JSON方法
    private static String buildDepartmentsJson(List<Map<String, Object>> departments) {
        StringBuilder json = new StringBuilder("[");
        for (int i = 0; i < departments.size(); i++) {
            if (i > 0) json.append(",");
            Map<String, Object> dept = departments.get(i);
            json.append("{")
                .append("\"id\":").append(dept.get("id")).append(",")
                .append("\"name\":\"").append(dept.get("name")).append("\",")
                .append("\"description\":\"").append(dept.get("description")).append("\"")
                .append("}");
        }
        json.append("]");
        return json.toString();
    }
    
    private static String buildDoctorsJson(List<Map<String, Object>> doctors) {
        StringBuilder json = new StringBuilder("[");
        for (int i = 0; i < doctors.size(); i++) {
            if (i > 0) json.append(",");
            Map<String, Object> doctor = doctors.get(i);
            json.append("{")
                .append("\"id\":").append(doctor.get("id")).append(",")
                .append("\"name\":\"").append(doctor.get("name")).append("\",")
                .append("\"title\":\"").append(doctor.get("title")).append("\",")
                .append("\"departmentId\":").append(doctor.get("departmentId"))
                .append("}");
        }
        json.append("]");
        return json.toString();
    }
}